package com.cnswhy.cloud.server.iot.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cnswhy.cloud.common.core.exception.BizException;
import com.cnswhy.cloud.common.core.mybatis.conditions.Wraps;
import com.cnswhy.cloud.common.core.utils.CnswhyUtil;
import com.cnswhy.cloud.common.core.utils.SystemClockUtil;
import com.cnswhy.cloud.common.logging.uitls.MDCUtil;
import com.cnswhy.cloud.common.rabbitmq.service.MessageService;
import com.cnswhy.cloud.common.redis.service.IdGeneratorService;
import com.cnswhy.cloud.common.redis.service.RedisService;
import com.cnswhy.cloud.server.common.entity.constant.AmqpExchange;
import com.cnswhy.cloud.server.common.entity.enumeration.IotType;
import com.cnswhy.cloud.server.common.entity.enumeration.OrderPfxEnum;
import com.cnswhy.cloud.server.common.entity.enumeration.PayType;
import com.cnswhy.cloud.server.common.entity.mq.OrderQueryMQ;
import com.cnswhy.cloud.server.core.dto.IotChargingLineTransOrderPageDTO;
import com.cnswhy.cloud.server.core.entity.*;
import com.cnswhy.cloud.server.core.query.QueryGenerator;
import com.cnswhy.cloud.server.core.service.*;
import com.cnswhy.cloud.server.core.vo.RespVo;
import com.cnswhy.cloud.server.iot.dto.ChangingLineMakeOrderDTO;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j

@Api(tags = "物联云创-充电线")
@Controller
@RequestMapping("/chargingline")
public class IotChargingLineController {
    @Autowired
    IotChargingLineInfoService iotChargingLineInfoService;
    @Autowired
    IotChargingLineMenuService iotChargingLineMenuService;
    @Autowired
    IotTerminalInfoService iotTerminalInfoService;
    @Autowired
    IotChargingLineTransOrderService iotChargingLineTransOrderService;
    @Autowired
    IdGeneratorService idGeneratorService;
    @Autowired
    SysConfigService sysConfigService;
    @Autowired
    MessageService messageService;
    @Autowired
    RedisService redisService;
    @Autowired
    WxPayService wxPayService;
    @Autowired
    IotChargingLineScaleService iotChargingLineScaleService;
    @Autowired
    IotChargingLineIndexInfoService iotChargingLineIndexInfoService;
    @ApiOperation(value = "查询充电线的状态", httpMethod = "GET")
    @ApiParam(name = "bo", value = "查询Bo")
    @RequestMapping(value = "/queryStatus/{terminalId}", method = {RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public RespVo queryStatus(HttpServletRequest request,@PathVariable String terminalId) {
        log.info("查询充电线ID：{}", terminalId);
        RespVo vo = new RespVo();
        try {
            if(StringUtils.isBlank(terminalId)){
                throw new BizException("终端设备号为空");
            }
            IotChargingLineInfo iotChargingLineInfo = iotChargingLineInfoService.getOne(Wraps.<IotChargingLineInfo>lbQ().eq(IotChargingLineInfo::getTerminalId, terminalId));
            if(iotChargingLineInfo == null){
                throw new BizException("终端设备不存在");
            }
            IotChargingLineInfo iotChargingLineInfo1 = (IotChargingLineInfo)redisService.hget(OrderPfxEnum.IOTCL.getCode(), terminalId);
            if(iotChargingLineInfo1 == null){
                //离线
                iotChargingLineInfo.setStatus(0);
                iotChargingLineInfoService.updateById(iotChargingLineInfo);
            }
            IotTerminalInfo iotTerminalInfo = iotTerminalInfoService.getOne(Wraps.<IotTerminalInfo>lbQ().eq(IotTerminalInfo::getTerminalId,iotChargingLineInfo.getTerminalId()).eq(IotTerminalInfo::getIotType, IotType.IOT_CHARG_LINE));
            if(iotTerminalInfo == null || iotTerminalInfo.getActiveStatus() == null || iotTerminalInfo.getActiveStatus() != 1){
                throw new BizException("终端信息未激活");
            }

            /*if(iotChargingLineInfo.getActiveStatus() == 0){
                throw new BizException("该终端未激活");
            }*/
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("iotChargingLineInfo",iotChargingLineInfo);
            List<IotChargingLineScale> iotChargingLineScaleList = iotChargingLineScaleService.list(Wraps.<IotChargingLineScale>lbQ().eq(IotChargingLineScale::getTerminalId,iotChargingLineInfo.getId()).orderByAsc(IotChargingLineScale::getHours));
            for(IotChargingLineScale iotChargingLineScale : iotChargingLineScaleList){
                iotChargingLineScale.setMenuAmt(iotChargingLineScale.getMenuAmt() > iotChargingLineScale.getMerchantAmt()? iotChargingLineScale.getMenuAmt() : iotChargingLineScale.getMerchantAmt());
            }
            jsonObject.put("IotChargingLineMenus",iotChargingLineScaleList);
            vo.setCode(RespVo.CODE_SUCCESS);
            vo.setResult(jsonObject);
            vo.setMessage("成功");
        }  catch (BizException e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage(e.getMessage());
        }catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("查询充电线信息失败");
            log.error("查询充电线信息失败", e);
        }
        return vo;
    }
    @ApiOperation(value = "下单", httpMethod = "GET")
    @RequestMapping(value = "/makeOrder", method = {RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public RespVo makeOrder(HttpServletRequest request, ChangingLineMakeOrderDTO changingLineMakeOrderDTO) {
        log.info("下单:{}", changingLineMakeOrderDTO.toString());
        RespVo vo = new RespVo();
        try {
            if(StringUtils.isBlank(changingLineMakeOrderDTO.getTerminalId())){
                throw new BizException("终端设备号为空");
            }
            if(changingLineMakeOrderDTO.getMenuId() == null){
                throw new BizException("菜单编号为空");
            }
            IotChargingLineInfo iotChargingLineInfo = iotChargingLineInfoService.getOne(Wraps.<IotChargingLineInfo>lbQ().eq(IotChargingLineInfo::getTerminalId, changingLineMakeOrderDTO.getTerminalId()));
            if(iotChargingLineInfo == null){
                throw new BizException("终端设备不存在");
            }
            IotChargingLineScale iotChargingLineScale = iotChargingLineScaleService.getById(changingLineMakeOrderDTO.getMenuId());
            if(iotChargingLineScale == null){
                throw new BizException("无效套餐名称");
            }
            IotTerminalInfo iotTerminalInfo = iotTerminalInfoService.getOne(Wraps.<IotTerminalInfo>lbQ().eq(IotTerminalInfo::getTerminalId, changingLineMakeOrderDTO.getTerminalId()));
            if(iotTerminalInfo == null){
                throw new BizException("终端设备信息不存在");
            }
            if(iotTerminalInfo.getActiveStatus() == null || iotTerminalInfo.getActiveStatus() != 1){
                throw new BizException("终端信息未激活");
            }
            WxPayUnifiedOrderRequest orderRequest =new WxPayUnifiedOrderRequest();
            String orderNum = OrderPfxEnum.IOTCL.getCode() + idGeneratorService.genCommonIdString();
            orderRequest.setOutTradeNo(orderNum);
            orderRequest.setOpenid(changingLineMakeOrderDTO.getOpenId());
            orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
            orderRequest.setSpbillCreateIp(CnswhyUtil.getHttpServletRequestIpAddress());
            orderRequest.setTotalFee(iotChargingLineScale.getMenuAmt().intValue());
            orderRequest.setBody("充电线付款:" + iotChargingLineScale.getMenuName());
            orderRequest.setNonceStr(String.valueOf(System.currentTimeMillis()));

            WxPayMpOrderResult object = wxPayService.createOrder(orderRequest);
            IotChargingLineTransOrder iotChargingLineTransOrder = new IotChargingLineTransOrder();
            iotChargingLineTransOrder.setTerminalId(changingLineMakeOrderDTO.getTerminalId());
            iotChargingLineTransOrder.setMerchantId(iotTerminalInfo.getMerchantId());
            iotChargingLineTransOrder.setMenuType(iotChargingLineScale.getMenuName());
            iotChargingLineTransOrder.setOrderId( orderNum);
            iotChargingLineTransOrder.setMenuId(iotChargingLineScale.getId());
            iotChargingLineTransOrder.setOpenId(orderRequest.getOpenid());
            iotChargingLineTransOrder.setTransAmt(iotChargingLineScale.getMenuAmt() > iotChargingLineScale.getMerchantAmt()? iotChargingLineScale.getMenuAmt() : iotChargingLineScale.getMerchantAmt());
            iotChargingLineTransOrder.setHours(iotChargingLineScale.getHours());
            iotChargingLineTransOrder.setStatus(1);

            iotChargingLineTransOrder.setPayType(PayType.wx.getVal());
            iotChargingLineTransOrderService.save(iotChargingLineTransOrder);
            OrderQueryMQ orderQueryMQ = OrderQueryMQ.builder().orderId(orderNum).queryTimes(0L).build();
            orderQueryMQ.setPayType(PayType.wx);
            orderQueryMQ.setBody(null);
            orderQueryMQ.setTraceId(MDCUtil.getTraceId());
            messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
            vo.setCode(RespVo.CODE_SUCCESS);
            vo.setResult(object);
            vo.setMessage("成功");
        }  catch (WxPayException e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage(e.getErrCodeDes());
        }  catch (BizException e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage(e.getMessage());
        }catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("查询充电线信息失败");
            log.error("查询充电线信息失败", e);
        }
        return vo;
    }

    @ApiOperation(value = "查看订单列表", httpMethod = "GET")
    @RequestMapping(value = "/orderList", method = {RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public RespVo orderList(HttpServletRequest request,  @RequestParam(name = "currentPage", defaultValue = "1") Integer currentPage,
                            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,String openId) {
        try{
            IotChargingLineTransOrder iotChargingLineTransOrder = new IotChargingLineTransOrder();
            iotChargingLineTransOrder.setOpenId(openId);
            iotChargingLineTransOrder.setStatus(2);
            QueryWrapper<IotChargingLineTransOrder> queryWrapper = QueryGenerator.initQueryWrapper(iotChargingLineTransOrder);
            queryWrapper.orderByDesc("create_time");
            Page<IotChargingLineTransOrder> page = new Page<>(currentPage, pageSize);
            IPage<IotChargingLineTransOrder> pageList = iotChargingLineTransOrderService.page(page, queryWrapper);
            return RespVo.success(pageList);
        } catch (BizException e) {
            return RespVo.fail(e.getMessage());
        } catch (Exception e) {
            return RespVo.fail("查询设备收费列表失败");
        }
    }


    @ApiOperation(value = "获取密码", httpMethod = "GET")
    @ApiParam(name = "terminalId", value = "终端编号")
    @RequestMapping(value = "/queryCode/{terminalId}", method = {RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public RespVo queryCode(HttpServletRequest request,@PathVariable String terminalId) {
        log.info("查询充电线ID：{}", terminalId);
        RespVo vo = new RespVo();
        try {
            if(StringUtils.isBlank(terminalId)){
                throw new BizException("终端设备号为空");
            }
            /*IotChargingLineInfo iotChargingLineInfo = iotChargingLineInfoService.getOne(Wraps.<IotChargingLineInfo>lbQ().eq(IotChargingLineInfo::getTerminalId, terminalId));
            if(iotChargingLineInfo == null){
                throw new BizException("终端设备不存在");
            }
            if(iotChargingLineInfo.getStatus() != 1 ){
                throw new BizException("终端设备不在线");
            }*/
            IotChargingLineInfo iotChargingLineInfo1 = (IotChargingLineInfo)redisService.hget(OrderPfxEnum.IOTCL.getCode(), terminalId);
            IotChargingLineInfo iotChargingLineInfo = iotChargingLineInfoService.getOne(Wraps.<IotChargingLineInfo>lbQ().eq(IotChargingLineInfo::getTerminalId, terminalId));

            if(iotChargingLineInfo1 == null){
                iotChargingLineInfo.setStatus(0);
                iotChargingLineInfoService.updateById(iotChargingLineInfo);
                throw new BizException("终端设备不在线");
            }
            vo.setCode(RespVo.CODE_SUCCESS);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code",getCode(iotChargingLineInfo));
            jsonObject.put("startTime", iotChargingLineInfo.getStartTime());
            jsonObject.put("endTime", iotChargingLineInfo.getEndTime());
            vo.setResult(jsonObject);
            vo.setMessage("成功");
        }  catch (BizException e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage(e.getMessage());
        }catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("查询充电线信息失败");
            log.error("查询充电线信息失败", e);
        }
        return vo;
    }
    public String getCode(IotChargingLineInfo iotChargingLineInfo){
        Long terminalId = Long.valueOf(iotChargingLineInfo.getTerminalId());
        IotChargingLineIndexInfo iotChargingLineIndexInfo = iotChargingLineIndexInfoService.getOne(
                Wraps.<IotChargingLineIndexInfo>lbQ().eq(IotChargingLineIndexInfo::getIndexId, terminalId.longValue() % 1000)
        );
        String aCode = iotChargingLineIndexInfo.getAIndex();
        String bCode = iotChargingLineIndexInfo.getBIndex();
        String cCode = iotChargingLineIndexInfo.getCIndex();
        String code = null;
        LocalDateTime startTime = SystemClockUtil.getLocalDateTime();
        java.time.Duration duration = java.time.Duration.between(startTime, iotChargingLineInfo.getEndTime());
        long minutes = duration.toMinutes() ;
        String codeIndex = null;
        int pfx = 0;
        if(minutes < 0){
            throw new BizException("无可用时间");
        } else if(minutes < 30L){
            //半小时
            codeIndex = "C";
            pfx = 4;
        }else if(minutes <= 300L){
            codeIndex = "A";
            pfx = (int)minutes / 60 + 1;
        }else if(minutes <= 600L ){
            codeIndex = "B";
            pfx = (int)minutes / 60 + 1 - 5;
        }else if(minutes <= 660L){
            codeIndex = "C";
            pfx = 1;
        }else if(minutes <= 720L){
            codeIndex = "C";
            pfx = 2;
        }else{
            codeIndex = "C";
            pfx = 3;
        }
        if("A".equals(codeIndex)){
            String[] aCodeList = aCode.split("\\|");
            code = aCodeList[iotChargingLineInfo.getAIndex()];
            iotChargingLineInfo.setAIndex(iotChargingLineInfo.getAIndex() + 1 > 24 ? 0 : iotChargingLineInfo.getAIndex() + 1);
        } else if("B".equals(codeIndex)){
            String[] aCodeList = bCode.split("\\|");
            code = aCodeList[iotChargingLineInfo.getBIndex()];
            iotChargingLineInfo.setBIndex(iotChargingLineInfo.getBIndex() + 1 > 24 ? 0 : iotChargingLineInfo.getBIndex() + 1);
        }else if("C".equals(codeIndex)){
            String[] aCodeList = cCode.split("\\|");
            code = aCodeList[iotChargingLineInfo.getCIndex()];
            iotChargingLineInfo.setCIndex(iotChargingLineInfo.getCIndex() + 1 > 24 ? 0 : iotChargingLineInfo.getCIndex() + 1);
        }
        iotChargingLineInfoService.updateById(iotChargingLineInfo);
        code = String.format("%d%s",pfx,code);
        return code;
    }

    public static void main(String[] args) {
        String aCode = "12412|34225|41425|45114|13251|54134|21155|24411|31532|13352|43115|51354|53531|12533|31443|35425|43355|14155|54541|31453|41125|45142|52533|13153|15244";
        String bCode = "12245|53154|34125|42453|12552|21532|43114|52511|13132|51152|21542|31425|14314|45411|25342|14354|13524|54242|12514|23341|41515|45313|32551|24412|34351";
        String cCode = "41512|42325|51314|42313|52133|45154|21453|45332|54542|41455|51221|41315|42511|52354|25425|42335|41335|51251|54231|51143|53145|15212|23525|31241|13523";
        String[] aCodeList = aCode.split("\\|");
        for (String a : aCodeList){
            System.out.println(a);
        }
    }
}
